package com.lzkjiot.service.gnss.utils;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.fusesource.mqtt.client.Future;
import org.fusesource.mqtt.client.FutureConnection;
import org.fusesource.mqtt.client.MQTT;
import org.fusesource.mqtt.client.QoS;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
@Slf4j
public class TbGatewayMqttClient {

    @Value("${tb.gateway.mqtt.url}")
    private String mqttUrl;

    @Value("${tb.gateway.mqtt.port}")
    private int mqttPort;

    @Value("${tb.gateway.mqtt.username}")
    private String mqttUsername;

    private FutureConnection connectionEcsGnss;

    @PostConstruct
    private void init(){
        log.info("=== init tbMqttClient ===");
        try {
            connectionEcsGnss = createConnection();
        } catch (Exception e){
            e.printStackTrace();
        }
    }


    private FutureConnection createConnection() throws Exception {
        MQTT mqtt = new MQTT();
        FutureConnection connection;
        mqtt.setHost(mqttUrl, mqttPort);
        mqtt.setUserName(mqttUsername);
        connection = mqtt.futureConnection();
        Future<Void> f1 = connection.connect();
        f1.await();
        log.warn("创建mqtt连接成功：{}:{}/{}",mqttUrl, mqttPort, mqttUsername);
        return connection;
    }

    private FutureConnection getConnection() {
        FutureConnection connection = null;
        if(connectionEcsGnss == null || !connectionEcsGnss.isConnected()){
            try {
                if(connectionEcsGnss != null && !connectionEcsGnss.isConnected()) {
                    Future<Void>  future = connectionEcsGnss.disconnect();
                    try {
                        log.warn("释放mqtt连接：{}:{}/{}",mqttUrl, mqttPort, mqttUsername);
                        future.await();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    connectionEcsGnss = null;
                }
                log.warn("创建mqtt连接成功：{}:{}/{}",mqttUrl, mqttPort, mqttUsername);
                connectionEcsGnss = createConnection();
            } catch (Exception e) {
                log.error("创建mqtt连接失败：{}:{}/{}",mqttUrl, mqttPort, mqttUsername);
            }
        }
        connection = connectionEcsGnss;
        return connection;
    }

    // v1/gateway/attributes
    public boolean publishAttributes(String deviceName, Map<String, Object> data){
        Map<String, Object> attrs = new HashMap<>();
        attrs.put(deviceName, data);
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode = mapper.valueToTree(attrs);
        FutureConnection connection = getConnection();
        Future<Void> futurePublishAttrs = connection.publish("v1/gateway/attributes", jsonNode.toString().getBytes(),
                QoS.AT_MOST_ONCE, false);
        try {
            futurePublishAttrs.await();
            log.info("推送设备【{}】属性数据成功.", deviceName);
            return true;
        } catch (Exception e) {
            log.error("推送设备【{}】属性数据失败：{}", deviceName, e.getMessage());
        }
        return false;
    }

    // v1/gateway/telemetry
    public boolean publishTelemetry(String deviceName, List<Map<String, Object>> data){
        Map<String, Object> attrs = new HashMap<>();
        attrs.put(deviceName, data);
        ObjectMapper mapper = new ObjectMapper();
        JsonNode jsonNode = mapper.valueToTree(attrs);
        FutureConnection connection = getConnection();
        Future<Void> futurePublishAttrs = connection.publish("v1/gateway/telemetry", jsonNode.toString().getBytes(),
                QoS.AT_MOST_ONCE, false);
        try {
            futurePublishAttrs.await();
            log.info("推送设备{}遥测数据成功.{}",deviceName, jsonNode.toString());
            return true;
        } catch (Exception e) {
            log.error("推送设备{}遥测数据失败 Cause：{}, data:{}", deviceName, e.getMessage(), jsonNode.toString());
        }
        return false;
    }
}
